package io.gitee.zhangbinhub.acp.boot

import io.gitee.zhangbinhub.acp.boot.conf.AcpCorsConfiguration
import io.gitee.zhangbinhub.acp.boot.constant.AcpCoreConstant
import io.gitee.zhangbinhub.acp.boot.exceptions.WebException
import io.gitee.zhangbinhub.acp.boot.http.HttpHeaders
import io.gitee.zhangbinhub.acp.boot.http.HttpStatus
import io.gitee.zhangbinhub.acp.core.common.CommonTools
import org.noear.solon.annotation.*
import org.noear.solon.core.handle.Context
import org.noear.solon.core.handle.FilterChain
import org.noear.solon.web.cors.CrossFilter

@Configuration
@Condition(onProperty = $$"${$${AcpCoreConstant.CORS_PREFIX}.enabled}=true")
class AcpBootCorsAutoConfiguration {
    @Bean(index = AcpCoreConstant.CORS_FILTER_ORDER)
    fun crossFilter(@Inject acpCorsConfiguration: AcpCorsConfiguration): CrossFilter = object : CrossFilter() {
        @Throws(WebException::class)
        override fun doFilter(ctx: Context, chain: FilterChain) {
            val origin = ctx.header(HttpHeaders.ORIGIN)
            if (!CommonTools.isNullStr(origin)) {
                doHandle(ctx)
                if (!CommonTools.isNullStr(ctx.headerOfResponse(HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN))) {
                    if (!ctx.handled) {
                        chain.doFilter(ctx)
                    }
                } else {
                    throw WebException(HttpStatus.FORBIDDEN, "Invalid CORS request")
                }
            }
        }
    }.apply {
        this.allowedOrigins(acpCorsConfiguration.allowedOrigins.joinToString(separator = ","))
        if (acpCorsConfiguration.allowedMethods.isEmpty()) {
            this.allowedMethods("*")
        } else {
            this.allowedMethods(acpCorsConfiguration.allowedMethods.joinToString(separator = ","))
        }
        if (acpCorsConfiguration.allowedHeaders.isEmpty()) {
            this.allowedHeaders("*")
        } else {
            this.allowedHeaders(acpCorsConfiguration.allowedHeaders.joinToString(separator = ","))
        }
        if (acpCorsConfiguration.exposedHeaders.isEmpty()) {
            this.exposedHeaders("*")
        } else {
            this.exposedHeaders(acpCorsConfiguration.exposedHeaders.joinToString(separator = ","))
        }
        this.allowCredentials(acpCorsConfiguration.allowCredentials)
        this.maxAge(acpCorsConfiguration.maxAge)
    }
}